home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
mxcode
/
gsrc211
/
musgus.asm
< prev
next >
Wrap
Assembly Source File
|
1994-03-14
|
69KB
|
2,435 lines
segment GUSSound
assume cs:GUSSound,ds:GUSSound
StartSoundSeg = $
proc MUS
push ax bx cx dx bp ds es
push ax
mov ax,cs
mov ds,ax
mov es,ax
pop ax
cld
cmp bx,0fh
ja @@HigherThanWeCount
cmp bx,0
jz @@DoIt
cmp [cs:MUSOK],1
jnz @@HigherThanWeCount
@@DoIt: shl bx,1
call [Word bx+JumpTable]
@@HigherThanWeCount:
pop es ds bp dx cx bx ax
retf
endp MUS
db 13,10,'Gravis UltraSound MOD Routines v2.1',0
db 13,10,'By Joshua C. Jensen',0
JumpTable dw offset MUS_Init ; Function 00
dw offset MUS_Close ; Function 01
dw offset MUS_SetVars ; Function 02
dw offset MUS_Nothing ; Function 03
dw offset MUS_PlayMusic ; Function 04
dw offset MUS_StopMusic ; Function 05
dw offset MUS_Nothing ; Function 06
dw offset MUS_SpeakerOn ; Function 07
dw offset MUS_SpeakerOff ; Function 08
dw offset MUS_ReturnInfo ; Function 09
dw offset MUS_SetInfo ; Function 0A
dw offset MUS_RetVoice ; Function 0B
dw offset MUS_RetMusicStatus ; Function 0C
dw offset MUS_DumpSampleDRAM ; Function 0D
;include "ptable.inc"
MUSOK db 0
PS16Header:
Sig db 'PS16■'
SongName db 75 dup (0)
SongLen db 0
numpatterns db 0
commentofs dd 0
Sequences db 128 dup (0)
Samples db 31*size PS16Sample dup (0)
PS16Size = $-PS16Header
PatternLoc dw 64 dup (0)
InsLoc dd 32 dup (0)
NumPatterns dw 0
Mus SMus <>
NumLines db 0
MusBuf dw 0
ChannelMap db 32 dup (0)
ChannelPriority db 32 dup (0)
include "vect.rt"
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_Nothing - Dead...
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_Nothing near
ret
endp MUS_Nothing
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_Init - Initialize the music routines.
; AX - GF1 IRQ (0 for detect)
; CX - MIDI IRQ
; DX - Base port (0 for detect)
; SI - DMA IN
; DI - DMA OUT
; Carry set - No Gravis Ultrasound
; Returns:
; SI - IRQ
; DI - Port
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_Init near
call u_DetectGUS
jnb @@FoundGUS
xor si,si
xor di,di
ret
@@FoundGUS: mov bx,[cs:GUSIRQ]
mov si,cs
mov di,offset GUSInt
call SetVect
mov [Word cs:IntStore],di
mov [Word cs:IntStore+2],si
call u_Reset
call MUS_SetMaxVolume
mov [Word cs:Mus+(offset (SMus).HeaderLoc)],offset PS16Header
mov [Word cs:Mus+(offset (SMus).HeaderLoc)+2],cs
; mov [Word cs:Mus+(offset (SMus).AnalyzerLoc)],offset AnalyzerHeights
; mov [Word cs:Mus+(offset (SMus).AnalyzerLoc)+2],cs
mov [Word cs:Mus+(offset (SMus).PatternLoc)],offset PatternLoc
mov [Word cs:Mus+(offset (SMus).PatternLoc)+2],cs
mov [Word cs:Mus+(offset (SMus).InsLoc)],offset InsLoc
mov [Word cs:Mus+(offset (SMus).InsLoc)+2],cs
mov [Word cs:Mus+(offset (SMus).ChannelLoc)],offset Channel1
mov [Word cs:Mus+(offset (SMus).ChannelLoc)+2],cs
mov [Word cs:Mus+(offset (SMus).mt_PeriodTable)],offset mt_PeriodTable
mov [Word cs:Mus+(offset (SMus).mt_PeriodTable)+2],cs
mov [Byte cs:MUSOK],1
mov si,[cs:GUSIRQ]
mov di,[cs:u_Base]
clc
ret
endp MUS_Init
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_Close - Kill all allocated segs, etc.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_Close near
call MUS_StopMusic
call u_Reset
mov bx,[cs:GUSIRQ]
mov di,[Word cs:IntStore]
mov si,[Word cs:IntStore+2]
call RestoreVect
mov [Byte cs:MUSOK],0
ret
endp MUS_Close
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SetVars - Sets various parameters for the card.
; AX - Sampling Rate (on SB, ignored here...)
; CL - Max Volume Setting
; CH - IRQ = 0 if default
; DX - GUS address
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SetVars near
mov [cs:MaxVolume],cl
or ch,ch
jz @@NoIRQChange
mov [Byte cs:GUSIRQ],ch
@@NoIRQChange: or dx,dx
jz @@NoAddrChange
mov [cs:u_Base],dx
add dx,102h
mov [cs:u_Voice],dx
inc dx
mov [cs:u_Command],dx
inc dx
mov [cs:u_DataLo],dx
inc dx
mov [cs:u_DataHi],dx
mov dx,[cs:u_Base]
add dx,6
mov [cs:u_Status],dx
add dx,2
mov [cs:u_TimerControl],dx
inc dx
mov [cs:u_TimerData],dx
@@NoAddrChange: ret
endp MUS_SetVars
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_PlayMusic - Make proper calls and interrupt sets for module playing.
; In: cx:si - PM Structure
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_PlayMusic near
push ds
mov ds,cx
mov ax,[si+(offset (PM).MusBuf)+2]
mov [cs:MusBuf],ax
mov ax,[si+PM.mt_speed]
cmp ax,-1
jz @@SkipSpeed
mov [Word cs:mt_speed],ax
@@SkipSpeed: mov ax,[si+PM.mt_counter]
cmp ax,-1
jz @@SkipCounter
mov [Word cs:mt_counter],ax
@@SkipCounter: mov ax,[si+PM.mt_SongPos]
mov [word cs:mt_SongPos],ax
mov ax,[si+PM.mt_PatternPos]
mov [Word cs:mt_PatternPos],ax
mov ax,cs
mov es,ax
mov di,offset PS16Header
push ds si
lds si,[si+PM.Header]
mov cx,PS16Size
rep movsb
pop si ds
mov di,offset PatternLoc
push ds si
lds si,[si+PM.PatternLoc]
mov cx,64*2
rep movsb
pop si ds
mov di,offset InsLoc
push ds si
lds si,[si+PM.InsLoc]
mov cx,32*4
rep movsb
pop si ds
mov [Byte cs:MStatus],0
call MUS_SetVoice
call u_Reset
mov bx,6
call u_TurnOnUserInt
pop ds
ret
endp MUS_PlayMusic
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_StopMusic - Shuts down the interrupts for generating music.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_StopMusic near
mov [Byte cs:MStatus],1
call u_TurnOffUserInt
call u_Reset
ret
endp MUS_StopMusic
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SpeakerOn - Turns output speaker on.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SpeakerOn near
mov dx,[cs:u_Base]
mov al,00000000b
out dx,al
ret
endp MUS_SpeakerOn
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SpeakerOff - Turns output speaker off.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SpeakerOff near
mov dx,[cs:u_Base]
mov al,00000010b
out dx,al
ret
endp MUS_SpeakerOff
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_ReturnInfo - Returns the SMUS structure location in SI:DI.
; In:
; CX - 1 = Copy info to SI:DI.
; 0 = Just return pointer.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_ReturnInfo near
mov ax,[cs:NumPatterns]
mov [cs:offset Mus+(offset (SMus).NumPatterns)],ax
mov al,[cs:mt_speed]
mov [cs:offset Mus+(offset (SMus).mt_speed)],al
mov al,[cs:mt_counter]
mov [cs:offset Mus+(offset (SMus).mt_counter)],al
mov ax,[cs:mt_PatternPos]
mov [cs:offset Mus+(offset (SMus).mt_PatternPos)],ax
mov al,[cs:mt_SongPos]
mov [cs:offset Mus+(offset (SMus).mt_SongPos)],al
mov al,[cs:PlayStatus]
mov [cs:offset Mus+(offset (SMus).PlayStatus)],al
mov ax,[cs:EditSeg]
mov [cs:offset Mus+(offset (SMus).EditSeg)],ax
mov ax,[cs:EditPat]
mov [cs:offset Mus+(offset (SMus).EditPat)],ax
mov ax,[cs:EditOfs]
mov [cs:offset Mus+(offset (SMus).EditOfs)],ax
mov al,[cs:MaxVolume]
mov [cs:offset Mus+(offset (SMus).MaxVolume)],al
mov al,[cs:SongLen]
mov [cs:offset Mus+(offset (SMus).songlen)],al
or cx,cx
jnz @@CopyIt
mov si,cs
mov di,offset Mus
ret
@@CopyIt: push ds es
mov es,si
mov ax,cs
mov ds,ax
mov si,offset Mus
mov cx,size Mus
rep movsb
pop es ds
ret
endp MUS_ReturnInfo
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SetInfo - Sets the SMUS structure location to whatever is in SI:DI.
; In:
; CX - 1 = Set Max Volume
; 2 = Set Pattern Info
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SetInfo near
push cx ds es
mov ds,si
mov si,di
mov ax,cs
mov es,ax
mov di,offset Mus
mov cx,size Mus
rep movsb
pop es ds
pop cx
cli
mov ax,[cs:offset Mus+(offset (SMus).NumPatterns)]
mov [cs:NumPatterns],ax
test cx,2
jz @@SkipSetPat
mov al,[cs:offset Mus+(offset (SMus).mt_speed)]
mov [cs:mt_speed],al
mov al,[cs:offset Mus+(offset (SMus).mt_counter)]
mov [cs:mt_counter],al
mov ax,[cs:offset Mus+(offset (SMus).mt_PatternPos)]
mov [cs:mt_PatternPos],ax
mov [cs:EditOfs],ax
mov al,[cs:offset Mus+(offset (SMus).mt_SongPos)]
mov [cs:mt_SongPos],al
mov [Byte PTr cs:EditPat],al
mov al,[cs:offset Mus+(offset (SMus).PlayStatus)]
mov [cs:PlayStatus],al
@@SkipSetPat: mov al,[cs:offset Mus+(offset (SMus).MaxVolume)]
mov [cs:MaxVolume],al
mov al,[cs:offset Mus+(offset (SMus).songlen)]
mov [cs:SongLen],al
test cx,1
jz @@Leave
call MUS_SetMaxVolume
@@Leave: sti
ret
endp MUS_SetInfo
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_RetVoice
; In: AX - Voice
; ES:DX - Buffer from DRAM
; CX - Length
;▓────────────────────────────────────────────────────────────────────────────▓
; Dump sample to DRAM
; ES:BX - Max 64k sample to dump to RAM.
; SI:DI - DRAM location to dump to.
; CX - Max bytes to dump.
; AH - Xor value.
proc MUS_RetVoice near
call u_ReadPos
call u_Peek
mov si,ax
ret
endp MUS_RetVoice
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_RetMusicStatus
; Out: SI - 1 Music Stopped
; DI - 1 Scope Triggered
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_RetMusicStatus near
mov al,[cs:MStatus]
xor ah,ah
mov si,ax
mov al,[cs:Trigger]
xor ah,ah
mov di,ax
mov [Byte cs:Trigger],0
ret
endp MUS_RetMusicStatus
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_DumpSampleDRAM
; CX - Sample Size
; SI:DI - Place in DRAM
; AX - Handle
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_DumpSampleDRAM near
mov bx,ax
call LoadDumpSample
ret
endp MUS_DumpSampleDRAM
; CX - Sample Size
; SI:DI - Place in DRAM
; BX - Handle
; DX - Sample Seg to read
LDSeg dw 0
proc LoadDumpSample near
push cx bx
mov [cs:LDSeg],dx
pop bx
push ds
mov ah,3Fh
mov dx,0
mov ds,[cs:LDSeg]
int 21h
pop ds
pop cx
mov es,[cs:LDSeg]
mov bx,0
mov ah,0
call u_DumpSampleToDRAM
ret
endp LoadDumpSample
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SetMaxVolume - Set the Master volumes for the channels to the max value.
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SetMaxVolume near
mov al,[Byte cs:MaxVolume]
mov [cs:offset Channel1+(offset (MS).MasterVolume)],al
mov [cs:offset Channel2+(offset (MS).MasterVolume)],al
mov [cs:offset Channel3+(offset (MS).MasterVolume)],al
mov [cs:offset Channel4+(offset (MS).MasterVolume)],al
ret
endp MUS_SetMaxVolume
;▓────────────────────────────────────────────────────────────────────────────▓
; MUS_SetVoice -
;▓────────────────────────────────────────────────────────────────────────────▓
proc MUS_SetVoice near
mov cx,16
mov bx,offset Channel1
@@Looper: mov ax,0
mov [Word cs:bx+MS.start],ax
mov ax,0f000h
mov [Word cs:bx+(offset (MS).start)+2],ax
add bx,size MS
loop @@Looper
ret
endp MUS_SetVoice
; GUS card routines.
MaxVoices = 31
IntStore dd 0
MIDIIRQ dw 0
GUSIRQ dw 0
DMAIn dw 0
DMAOut dw 0
u_Base dw 0
proc UDelay
push dx ax
mov dx,300h
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
pop ax dx
ret
endp UDelay
; BX:CX Set to whatever.
proc u_Peek
pushf
cli
push dx
mov dx,[cs:u_Command]
mov al,43h
out dx,al
inc dx ; 104h
mov ax,cx
out dx,ax
dec dx ; 103h
mov al,44h
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
in al,dx
pop dx
popf
ret
endp u_Peek
; BX:CX Set to whatever.
; AX Value to poke
proc u_Poke
pushf
cli
push dx ax
mov dx,[cs:u_Command]
mov al,43h
out dx,al
inc dx
mov ax,cx
out dx,ax
dec dx
mov al,44h
out dx,al
add dx,2
mov al,bl
out dx,al
add dx,2
pop ax
out dx,al
in al,dx
pop dx
popf
ret
endp u_Poke
; DX - u_Base.
proc u_Probe
pushf
cli
mov dx,[cs:u_Command]
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,0
out dx,al
call UDelay
call UDelay
sub dx,2 ; 103h
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,1
out dx,al
call UDelay
call UDelay
mov ax,0AAh
mov bx,0
mov cx,0
call u_Poke
mov ax,055h
mov bx,1
call u_Poke
mov bx,0
call u_Peek
push ax
mov ax,0
call u_Poke
sub dx,2 ; 103h
mov al,4Ch
out dx,al
add dx,2 ; 105h
mov al,0
out dx,al
pop ax
popf
cmp al,0AAh
jnz @@Nope
clc
ret
@@Nope: stc
ret
endp u_Probe
GUSChangeIRQ db 0,0,1,3,0,2,0,4,0,0,0,5,6,0,0,7
GUSChangeDMA db 1,0,2,0,3,4,5
;1 5
proc u_SetInterface
cmp [Word cs:GUSIRQ],0
jz @@Exit
cli
mov bx,[cs:MIDIIRQ]
mov cl,[cs:bx+GUSChangeIRQ]
shl cl,3
mov bx,[cs:GUSIRQ]
or cl,[cs:bx+GUSChangeIRQ]
cmp bx,[cs:MIDIIRQ]
jnz @@JustStore
or cl,40h
@@JustStore:
push cx
mov bx,[cs:DMAOut]
dec bx
mov cl,[cs:bx+GUSChangeDMA]
mov dx,cx
shl dl,3
mov bx,[cs:DMAIn]
dec bx
mov cl,[cs:bx+GUSChangeDMA]
inc bx
cmp bx,[cs:DMAOut]
jnz @@Fix
or cl,40h
jmp @@JustStore2
@@Fix: or cl,dl
@@JustStore2:
mov bl,cl
pop cx
mov dx,[cs:u_Base]
mov al,8
out dx,al
add dx,0Bh
mov al,bl
or al,80h
out dx,al
mov dx,[cs:u_Base]
mov al,48h
out dx,al
add dx,0Bh
mov al,cl
out dx,al
mov dx,[cs:u_Base]
mov al,8
out dx,al
add dx,0Bh
mov al,bl
out dx,al
mov dx,[cs:u_Base]
mov al,48h
out dx,al
add dx,0Bh
mov al,cl
out dx,al
mov dx,[cs:u_Base]
add dx,102h
mov al,0
out dx,al
mov dx,[cs:u_Base]
mov al,9
out dx,al
mov dx,[cs:u_Base]
add dx,102h
mov al,0
out dx,al
sti
@@Exit: ret
endp u_SetInterface
proc u_Reset
call u_SetInterface
cli
mov bx,[cs:u_Command]
mov cx,[cs:u_DataHi]
mov dx,bx
mov al,4Ch
out dx,al
mov dx,cx
mov al,0
out dx,al
call UDelay
call UDelay
mov dx,bx
mov al,4Ch
out dx,al
mov dx,cx
mov al,1
out dx,al
call UDelay
call UDelay
mov dx,[cs:u_Voice]
add dx,100h
mov al,3
out dx,al
call UDelay
mov dx,[cs:u_Voice]
add dx,100h
mov al,0
out dx,al
mov dx,bx
mov al,41h
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,45h
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,49h
out dx,al
mov dx,cx
mov al,0
out dx,al
mov dx,bx
mov al,0Eh
out dx,al
add dx,2
mov al,MaxVoices
or al,0C0h
out dx,al
mov dx,[cs:u_Status]
in al,dx
mov dx,bx
mov al,41h
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,49h
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,8Fh
out dx,al
mov dx,cx
in al,dx
push bx cx
mov cx,0
@@VoiceClearLoop:
mov dx,[cs:u_Voice]
mov al,cl
out dx,al
inc dx
mov al,9
out dx,al
inc dl
mov ax,0
out dx,ax
dec dl
mov al,0
out dx,al
add dx,2
mov al,3 ; Turn voice off
out dx,al
sub dx,2
mov al,0Dh
out dx,al
add dx,2
mov al,3
out dx,al
sub dx,2
inc cx
cmp cx,32
jnz @@VoiceClearLoop
pop cx bx
mov dx,bx
mov al,41h
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,49h
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,8Fh
out dx,al
mov dx,cx
in al,dx
mov dx,bx
mov al,4Ch
out dx,al
mov dx,cx
mov al,7
out dx,al
sti
ret
endp u_Reset
; CX:AX - Number
proc RShift
mov bx,cx
shr ax,7
shr cx,7
shl bx,9
or ax,bx
ret
endp RShift
; AX - Voice
; Returns: DX:AX - Position
proc u_ReadPos
pushf
cli
mov dx,[cs:u_Voice]
out dx,al
inc dx ; 103h
mov al,8ah
out dx,al
inc dx ; 104h
in ax,dx ; TEMP0
mov cx,ax
dec dx ; 103h
mov al,8bh
out dx,al
inc dx ; 104h
in ax,dx ; TEMP1
xor dx,dx
mov bx,cx
shl cx,7
shl dx,7
shr bx,9
or dx,bx
shr ax,9
and ax,7Fh
or cx,ax
mov ax,cx
popf
ret
endp u_ReadPos
; Dump sample to DRAM
; ES:BX - Max 64k sample to dump to RAM.
; SI:DI - DRAM location to dump to.
; CX - Max bytes to dump.
; AH - Xor value.
proc u_DumpSampleToDRAM
cli
push cx
mov dx,[cs:u_Command]
mov al,44h ; Dump upper byte, only do it on carry from now
out dx,al ; on.
add dx,2
push ax
mov ax,si
out dx,al
pop ax
sub dx,2
@@MainLoop:
mov al,43h
out dx,al
inc dx
push ax
mov ax,di
out dx,ax
pop ax
dec dx
@@DumpByte:
add dx,4
mov al,[es:bx]
xor al,ah
inc bx
out dx,al
sub dx,4
add di,1
jnc @@DoLoop
inc si
mov al,44h
out dx,al
add dx,2
push ax
mov ax,si
out dx,al
pop ax
sub dx,2
@@DoLoop:
loop @@MainLoop
pop cx
sti
ret
endp u_DumpSampleToDRAM
u_Voice dw 0
u_Command dw 0
u_DataLo dw 0
u_DataHi dw 0
u_Status dw 0
u_TimerControl dw 0
u_TimerData dw 0
u_adlibcontrol db 0
u_timermask db 0
u_IRQs db 2,3,5,7,11,12,15
u_IntStore dd 0,0,0,0,0,0,0
proc u_SetPorts
mov dx,[cs:u_Base]
add dx,102h
mov [cs:u_Voice],dx
inc dx
mov [cs:u_Command],dx
inc dx
mov [cs:u_DataLo],dx
inc dx
mov [cs:u_DataHi],dx
mov dx,[cs:u_Base]
add dx,6
mov [cs:u_Status],dx
add dx,2
mov [cs:u_TimerControl],dx
inc dx
mov [cs:u_TimerData],dx
ret
endp u_SetPorts
; In:
; DX - Base (0 for detect)
; CX - MIDI IRQ
; AX - IRQ (0 for detect)
; Carry set - No GUS
; No carry - GUS at u_Base
proc u_DetectGUS
mov [cs:GUSIRQ],ax
mov [cs:MIDIIRQ],cx
mov [cs:DMAIn],si
mov [cs:DMAOut],di
mov [cs:u_Base],dx
call u_SetPorts
clc
ret
endp u_DetectGUS
; bx - Speed (0-255) (* 80 microseconds)
proc u_TurnOnUserInt
cli
or [Byte cs:u_adlibcontrol],4
or [Byte cs:u_timermask],1
mov dx,[cs:u_Command]
mov al,46h
out dx,al
add dx,2
mov al,bl
out dx,al
sub dx,2
mov al,45h
out dx,al
add dx,2
mov al,[cs:u_adlibcontrol]
out dx,al
mov dx,[cs:u_TimerControl]
mov al,4
out dx,al
inc dx
mov al,[cs:u_timermask]
out dx,al
sti
ret
endp u_TurnOnUserInt
proc u_TurnOffUserInt
cli
and [Byte cs:u_adlibcontrol],0FBh
and [Byte cs:u_timermask],0FEh
mov dx,[cs:u_Command]
mov al,45h
out dx,al
add dx,2
mov al,[cs:u_adlibcontrol]
out dx,al
call u_Reset
sti
ret
endp u_TurnOffUserInt
irqstatus db 0
proc GUSInt
pusha
push ds es
mov dx,[cs:u_Status]
in al,dx
mov [cs:irqstatus],al
@@TopOfInt: test [Byte cs:irqstatus],4
jz @@CheckNext
mov dx,[cs:u_Command]
mov al,45h
out dx,al
and [Byte cs:u_adlibcontrol],0FBh
add dx,2
mov al,[cs:u_adlibcontrol]
out dx,al
or [Byte cs:u_adlibcontrol],4
mov al,[cs:u_adlibcontrol]
out dx,al
call sd_UpdateChannels
cmp [Byte cs:MStatus],1
jnz @@CheckNext
call u_TurnOffUserInt
call u_Reset
@@CheckNext: mov dx,[cs:u_Command]
mov al,8Fh
out dx,al
add dx,2
in al,dx
@@Finish:
mov al,20h
out 0A0h,al
mov al,20h
out 20h,al
sti
pop es ds
popa
iret
endp GUSInt
proc FindOpenChannel
mov bx,0
@@Looper: cmp [cs:bx+ChannelMap],0
jz @@Open
inc bx
cmp bx,32
jnz @@Looper
; If we made it this far, check the priorities to turn one off.
mov dx,0
mov cx,0FFh ; Max Priority
mov bx,0
@@PLooper: cmp [cs:bx+ChannelPriority],cl
jl @@Change
jmp @@IncIt
@@Change: mov cl,[cs:bx+ChannelPriority]
mov dx,bx
@@IncIt: inc bx
cmp bx,32
jnz @@PLooper
mov bx,ax
@@Open: mov ax,bx
ret
endp FindOpenChannel
;┌──────────────────────────────────────────────────────────────────────────┐
;│││──────────────────────── Protracker Stuff ────────────────────────────│││
;└──────────────────────────────────────────────────────────────────────────┘
;┌─┐ Protracker specific
;└─┘ variables.
mt_speed db 6
mt_counter db 0
mt_PatternPos dw 0
mt_SongPos db 0
mt_PattDelayTime2 db 0
mt_PattDelayTime db 0
mt_PBreakFlag db 0
mt_PBreakPos db 0
mt_PosJumpFlag db 0
mt_LowMask db 0FFh
Trigger db 0
mt_VibratoTable: db 0, 24, 49, 74, 97,120,141,161
db 180,197,212,224,235,244,250,253
db 255,253,250,244,235,224,212,197
db 180,161,141,120, 97, 74, 49, 24
Channel1 MS <0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 0,0,0>
Channel2 MS <0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 1,0,0>
Channel3 MS <0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 2,0,0>
Channel4 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 3,0,0>
Channel5 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 4,0,0>
Channel6 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 5,0,0>
Channel7 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 6,0,0>
Channel8 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 7,0,0>
Channel9 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 8,0,0>
Channel10 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 9,0,0>
Channel11 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,10,0,0>
Channel12 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,11,0,0>
Channel13 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,12,0,0>
Channel14 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,13,0,0>
Channel15 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,14,0,0>
Channel16 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,15,0,0>
PlayStatus db 1
MStatus db 0
EditPat dw 0
EditSeg dw 0
EditOfs dw 0
ChangeIns db 0
MaxVolume db 200
EfxFlag db 0
mt_VolTable dw 00E00h,0B000h,0B800h,0BC00h,0BE00h,0C000h,0C400h,0C800h,0CC00h
dw 0D000h,0D200h,0D400h,0D600h,0D800h,0DA00h,0DC00h,0DE00h
dw 0E000h,0E100h,0E200h,0E300h,0E400h,0E500h,0E600h,0E700h
dw 0E800h,0E900h,0EA00h,0EB00h,0EC00h,0ED00h,0EE00h,0EF00h
dw 0F080h,0F100h,0F180h,0F200h,0F280h,0F300h,0F380h,0F400h
dw 0F480h,0F500h,0F580h,0F600h,0F680h,0F700h,0F780h,0F800h
dw 0F880h,0F900h,0F980h,0FA00h,0FA80h,0FB00h,0FB80h,0FC00h
dw 0FC80h,0FD00h,0FD80h,0FE00h,0FE80h,0FF00h,0FF80h,0FFF0h
include "period.asm"
macro SetVoice
mov [Byte cs:Voice],cl
mov dx,[cs:u_Voice]
mov al,[cs:si+MS.sc_Voice]
out dx,al
endm SetVoice
Voice db 0
macro PlayVol
local Done
mov dx,[cs:u_Command]
mov al,89h
out dx,al
inc dl
in ax,dx
cmp ax,[cs:si+MS.sc_Vol]
jz Done
mov ax,[cs:si+MS.sc_Vol]
call slideramp
Done:
endm PlayVol
macro PlayNote
local Done
mov dx,[cs:u_Command]
mov al,81h
out dx,al
inc dl
in ax,dx
cmp ax,[cs:si+MS.sc_Note]
jz Done
dec dl
mov al,1
out dx,al
inc dl
mov ax,[cs:si+MS.sc_Note]
out dx,ax
Done:
endm PlayNote
proc DecompressPattern near
push di
mov ax,es
mov ds,ax
mov ax,[cs:MusBuf]
mov es,ax
mov di,0
mov cx,3072/2
mov ax,0
rep stosw
mov si,0
mov di,0
mov al,[si+2]
mov [cs:NumLines],al
add si,3
mov cx,0
@@ChannelLoop: push cx
mov di,cx
shl cx,1
add di,cx ; * 3
@@LineLoop: xor ah,ah
lodsb
cmp al,-1
jz @@NextChannel
push di
mov bx,ax
shl ax,5 ; * 32
shl bx,4 ; * 16
add di,ax
add di,bx
movsb
movsw
pop di
jmp @@LineLoop
@@NextChannel: pop cx
inc cx
cmp cx,16
jnz @@ChannelLoop
pop di
ret
endp DecompressPattern
;╒═══════════════════════════════════════════════════════════════════════════╕
;│ NAME : sd_UpdateChannels │
;│ *** Original code: Amiga Protracker by Lars Hamre. │
;│ *** Converted by Joshua C. Jensen. │
;╘═══════════════════════════════════════════════════════════════════════════╛
proc DecProc near
cmp [cs:si+MS.DecVolume],0
ja @@AllRight
mov [Byte cs:si+MS.DecVolume],1
@@AllRight:
dec [Byte cs:si+MS.DecVolume]
ret
endp DecProc
proc sd_UpdateChannels near
mov ax,cs
mov ds,ax
mov es,ax
mt_ContinueUpdate:
inc [Byte cs:mt_counter]
mov al,[cs:mt_counter]
cmp al,[cs:mt_speed]
jb mt_NoNewNote
mov [Byte cs:mt_counter],0
cmp [Byte cs:mt_PattDelayTime2],0
jz mt_GetNewNote
call mt_NoNewAllChannels
jmp mt_dskip
mt_NoNewNote:
call mt_NoNewAllChannels
jmp mt_NoNewPosYet
mt_NoNewAllChannels:
mov cx,16
mov si,offset Channel1
mt_NoNewLoop:
push cx si
call DecProc
SetVoice
call mt_CheckEfx
PlayNote
PlayVol
pop si
add si,size MS
pop cx
loop mt_NoNewLoop
ret
mt_GetNewNote:
xor ax,ax
mov al,[cs:mt_SongPos]
mov di,ax
mov [Word cs:EditPat],ax
mov al,[cs:di+Sequences]
shl al,1
mov di,offset PatternLoc
add di,ax
mov es,[cs:di]
mov di,[cs:mt_PatternPos]
call DecompressPattern
mov [Word cs:EditSeg],es
mov [Word cs:EditOfs],di
mov cx,16
mov si,offset Channel1
mt_GetNewLoop:
push cx si
call DecProc
SetVoice
call mt_PlayVoice
PlayNote
PlayVol
pop si
add si,size MS
pop cx
loop mt_GetNewLoop
jmp mt_dskip
mt_PlayVoice:
mov [Byte cs:EfxFlag],0
mov [Byte cs:ChangeIns],0
cmp [Byte cs:si],0
jnz mt_plvskip
cmp [Word cs:si+1],0
jnz mt_plvskip
call mt_PerNop
mt_plvskip:
mov al,[es:di]
mov [cs:si+MS.note],al
mov ax,[es:di+1]
mov [Word cs:si+MS.cmd],ax
add di,3
mov al,[cs:si+MS.cmd]
and al,0F0h
shr al,4
mov ah,[Byte cs:si+MS.note]
and ah,11000000b
shr ah,2
or al,ah ; Is there an ins?
jz mt_SetRegisters
mov [Byte cs:ChangeIns],1
mov [cs:si+MS.sc_Mode],0
dec al
mov bl,al
mov [cs:si+MS.SampleNum],al
mov bh,size PS16Sample
mul bh
mov dx,ax
xor bh,bh
shl bx,2
add bx,offset InsLoc
mov ax,[cs:bx]
mov [Word cs:si+MS.start],ax
mov ax,[cs:bx+2]
mov [Word cs:si+(offset (MS).start)+2],ax
mov bx,dx
add bx,offset Samples
mov cx,[cs:bx+PS16Sample.length]
mov [Word cs:si+MS.length],cx
mov [Word cs:si+(offset (MS).length)+2],0
mov ax,[Word cs:bx+PS16Sample.volume]
mov [Word cs:si+MS.finetune],ax
mov al,ah
call volequ
mov cx,[cs:bx+PS16Sample.replen]; Get the Repeat length.
cmp cx,2
jbe mt_NoLoop
or [Byte cs:si+MS.sc_Mode],00001000b
mov cx,[cs:bx+PS16Sample.repeat]
or cx,cx
je mt_LoopNoFix
dec cx
mt_LoopNoFix:
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
add ax,cx
adc dx,0
mov [Word cs:si+MS.loopstart],ax
mov [Word cs:si+(offset (MS).loopstart)+2],dx
mov [Word cs:si+MS.wavestart],ax
mov [Word cs:si+(offset (MS).wavestart)+2],dx
mov cx,[Word cs:bx+PS16Sample.replen]
; dec cx
add ax,cx
adc dx,0
mov [Word cs:si+MS.replen],ax
mov [Word cs:si+(offset (MS).replen)+2],dx
jmp mt_SetRegisters
mt_NoLoop:
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
mov [Word cs:si+MS.loopstart],ax
mov [Word cs:si+(offset (MS).loopstart)+2],dx
mov [Word cs:si+MS.wavestart],ax
mov [Word cs:si+(offset (MS).wavestart)+2],dx
mov cx,[Word cs:bx+PS16Sample.length]
dec cx
add ax,cx
adc dx,0
mov [Word cs:si+MS.replen],ax
mov [Word cs:si+(offset (MS).replen)+2],dx
mt_SetRegisters:
mov al,[cs:si+MS.note]
and al,00111111b
jnz mt_ThereIsANote
jmp mt_CheckMoreEfx
mt_ThereIsANote:
mov ax,[Word cs:si+MS.cmd]
xchg ah,al
and ax,0FF0h
cmp ax,0E50h
jz mt_DoSetFineTune
cmp ah,3 ; Is it a tone portamento?
jz mt_ChkTonePorta
cmp ah,5 ; Is it a tone and volume slide?
jz mt_ChkTonePorta
cmp ah,9 ; Is it a sample offset command?
jnz mt_SetPeriod
call mt_CheckMoreEfx
jmp mt_SetPeriod
mt_DoSetFineTune:
call mt_SetFineTune
jmp mt_SetPeriod
mt_ChkTonePorta:
call mt_SetTonePorta
jmp mt_CheckMoreEfx
mt_SetPeriod:
mov [Byte cs:ChangeIns],1
mov bl,[cs:si+MS.note]
and bx,00111111b
dec bx
shl bx,1
mov al,[cs:si+MS.finetune]
mov cl,61*2
mul cl
add bx,ax
mov ax,[Word cs:bx+mt_PeriodTable]
mov [cs:si+MS.period],ax
mov ax,[Word cs:si+MS.cmd]
xchg ah,al
and ax,0FF0h
cmp ax,0ED0h
jnz mt_NotANoteCut
jmp mt_CheckMoreEfx
mt_NotANoteCut:
mov al,[cs:si+MS.wavecontrol] ; Get the wavecontrol.
and al,00000100b ; Amiga: BTST #2,wavecontrol.
jz mt_vibnoc ; If it is zero, then skip.
mov [Byte cs:si+MS.vibratopos],0
mt_vibnoc:
mov al,[cs:si+MS.wavecontrol] ; Get it again.
and al,01000000b ; Amiga: BTST #6,wavecontrol
jz mt_trenoc ; If it is zero, then skip.
mov [Byte cs:si+MS.tremolopos],0 ; Zero the Tremolo offset.
mt_trenoc:
cmp [Byte cs:ChangeIns],1
jnz mt_SetGeneral
mt_DoIns:
; high byte of sample start == F000H, turn off the voice
cmp [Word cs:si+(offset (MS).start)+2],0f000h
jz @@NoVoice
push dx ax
mov al,0
call doramp
mov dx,[cs:u_Command]
mov al,0
out dx,al
mov al,3
add dl,2
out dx,al
xor [cs:si+MS.sc_Voice],16
mov dx,[cs:u_Voice]
mov al,[cs:si+MS.sc_Voice]
out dx,al
pop ax dx
; Send sample begin
@@DoBegin:
mov dx,[cs:u_Command]
mov al,0ah
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.start]
mov cx,[Word cs:si+(offset (MS).start)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,0bh
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.start]
shl ax,9
out dx,ax
mov dx,[cs:u_Command]
mov al,2
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.loopstart]
mov cx,[Word cs:si+(offset (MS).loopstart)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,3
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.loopstart]
shl ax,9
out dx,ax
mov dx,[cs:u_Command]
mov al,4
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.replen]
mov cx,[Word cs:si+(offset (MS).replen)+2]
call RShift
out dx,ax
dec dx ; 103h
mov al,5
out dx,al
inc dx ; 104h
mov ax,[Word cs:si+MS.replen]
shl ax,9
out dx,ax
dec dx ; 103h
mov al,0
out dx,al
add dx,2
mov al,[Byte cs:si+MS.sc_Mode]
out dx,al
mt_SetGeneral:
call mt_PerNop
mov dx,[cs:u_Command]
mov al,0ch
out dx,al
add dx,2
mov al,[cs:si+MS.sc_PanPosition]
out dx,al
sub dx,2
jmp @@Bottom
; Shuts off the voice
@@NoVoice:
mov al,0
call doramp
mov al,0
out dx,al
add dl,2
mov al,3
out dx,al
@@Bottom:
@@Done:
mov ax,[cs:si+MS.period]
; call SpectrumAnalyzer
; ST n_trigger(A6)
mov [Byte cs:Trigger],1
cmp [Byte cs:EfxFlag],1
jz @@Skip
call mt_CheckMoreEfx
@@Skip: ret
endp sd_UpdateChannels
proc mt_dskip near
mov [Word cs:EditSeg],es
mov ax,[Word cs:mt_PatternPos]
mov [Word cs:EditOfs],ax
add [Word cs:mt_PatternPos],48
mov al,[cs:mt_PattDelayTime]
or al,al
jz mt_dskc
mov [cs:mt_PattDelayTime2],al
mov [Byte cs:mt_PattDelayTime],0
mt_dskc:
cmp [Byte cs:mt_PattDelayTime2],0
jz mt_dska
dec [Byte cs:mt_PattDelayTime2]
jz mt_dska
sub [Word cs:mt_PatternPos],48
mt_dska:
cmp [Byte cs:mt_PBreakFlag],0
jz mt_nnpysk
mov [Byte cs:mt_PBreakFlag],0
xor ax,ax
mov al,[cs:mt_PBreakPos]
mov [cs:mt_PBreakPos],ah
mov bx,48
mul bx
mov [cs:mt_PatternPos],ax
mt_nnpysk:
cmp [Word cs:mt_PatternPos],1024*3
jb mt_NoNewPosYet
mt_NextPosition:
xor ax,ax
mov al,[cs:mt_PBreakPos]
mov bx,48
mul bx
mov [cs:mt_PatternPos],ax
mov [Byte cs:mt_PBreakPos],0
mov [Byte cs:mt_PosJumpFlag],0
inc [Byte cs:mt_SongPos]
and [Byte cs:mt_SongPos],7Fh
mov al,[cs:mt_SongPos]
cmp al,[cs:SongLen]
jnz mt_NoNewPosYet
mov [Byte cs:mt_SongPos],0
cmp [Byte cs:PlayStatus],1
jnz @@Quit
mov [Byte cs:mt_SongPos],0
ret
;---------------------------------------------------
@@Quit: mov [Byte cs:MStatus],1
mov [Byte cs:mt_SongPos],0
ret
mt_NoNewPosYet:
cmp [Byte cs:mt_PosJumpFlag],0
jnz mt_NextPosition
ret
endp mt_dskip
proc mt_CheckEfx near
mov ax,[Word cs:si+MS.cmd]
xchg al,ah
and ax,0FFFh
jz mt_Return
mov bl,[cs:si+MS.cmd]
and bl,0Fh
cmp bl,0
jz mt_Arpeggio
cmp bl,1
jz mt_PortaUp
cmp bl,2
jz mt_PortaDown
cmp bl,3
jz mt_TonePortamento
cmp bl,4
jz mt_Vibrato
cmp bl,5
jz mt_TonePlusVolSlide
cmp bl,6
jz mt_VibratoPlusVolSlide
cmp bl,0Eh
jz mt_E_Commands
SetBack:call mt_PerNop
cmp bl,7
jz mt_Tremolo
cmp bl,0Ah
jz mt_VolumeSlide
mt_Return:
ret
endp mt_CheckEfx
; Effect 0 -- Arpeggio
proc mt_Arpeggio near
xor ax,ax
mov al,[cs:mt_counter]
mov bl,3
div bl
xchg al,ah
cmp al,1
jz mt_Arpeggio1
cmp al,2
jz mt_Arpeggio2
mt_Arpeggio0:
mov cx,[cs:si+MS.period]
jmp ArpeggioSet
mt_Arpeggio1:
xor ax,ax
mov al,[Byte cs:si+MS.cmdlo]
shr al,4
jmp ArpeggioFind
mt_Arpeggio2:
xor ax,ax
mov al,[cs:si+MS.cmdlo]
and al,15
ArpeggioFind:
shl ax,1
mov bx,ax
mov al,[cs:si+MS.finetune]
mov cl,61*2
mul cl
mov dx,[cs:si+MS.period]
push di
mov di,offset mt_PeriodTable
add di,ax
mov cx,60
mt_arploop:
mov ax,[cs:bx+di]
cmp dx,[cs:di]
jnb mt_arpafterloop
add di,2
loop mt_arploop
pop di
ret
mt_arpafterloop:
pop di
mov cx,ax
ArpeggioSet:
call mt_PerNop2
ret
endp mt_Arpeggio
; Effect 1 -- Portamento Up
proc mt_PortaUp near
xor ax,ax
mov al,[cs:si+MS.cmdlo]
and al,[cs:mt_LowMask]
mov [Byte cs:mt_LowMask],0FFh
sub [cs:si+MS.period],ax
mov cx,[cs:si+MS.period]
and cx,0FFFh
cmp cx,71h
jnb mt_PortaUSkip
and [cs:si+MS.period],0F000h
or [cs:si+MS.period],71h
mt_PortaUSkip:
mov cx,[cs:si+MS.period]
and cx,0FFFh
call mt_PerNop
ret
endp mt_PortaUp
; Effect 2 -- Portamento Down
proc mt_PortaDown near
xor ax,ax
mov al,[cs:si+MS.cmdlo]
and al,[cs:mt_LowMask]
mov [Byte cs:mt_LowMask],0FFh
add [cs:si+MS.period],ax
mov cx,[cs:si+MS.period]
and cx,0FFFh
cmp cx,358h
jb mt_PortaDSkip
and [cs:si+MS.period],0F000h
or [cs:si+MS.period],856
mt_PortaDSkip:
mov cx,[cs:si+MS.period]
and cx,0FFFh
call mt_PerNop
ret
endp mt_PortaDown
proc mt_SetTonePorta near
push di
mov di,offset mt_PeriodTable
mov bl,[cs:si+MS.note]
and bx,00111111b
dec bx
shl bx,1
mov dx,[Word cs:bx+di]
xor ax,ax
mov al,[cs:si+MS.finetune]
mov cl,61*2
mul cl
add di,ax
mov bx,0
mt_StpLoop:
cmp dx,[cs:bx+di]
jnb mt_StpFound
add bx,2
cmp bx,61*2
jb mt_StpLoop
mov bx,59*2
mt_StpFound:
mov dl,[cs:si+MS.finetune]
and dl,8
jz mt_StpGoss
or bx,bx
jz mt_StpGoss
sub bx,2
mt_StpGoss:
mov dx,[cs:bx+di]
pop di
mov [cs:si+MS.wantedperiod],dx
mov ax,[cs:si+MS.period]
mov [Byte cs:si+MS.toneportdirec],0
cmp dx,ax
jz mt_ClearTonePorta
jnb mt_Return
mov [Byte cs:si+MS.toneportdirec],1
ret
mt_ClearTonePorta:
mov [Word cs:si+MS.wantedperiod],0
ret
endp mt_SetTonePorta
; Effect 3 -- Tone Portamento
proc mt_TonePortamento near
mov al,[cs:si+MS.cmdlo]
or al,al
jz mt_TonePortNoChange
mov [cs:si+MS.toneportspeed],al
mov [Byte cs:si+MS.cmdlo],0
mt_TonePortNoChange:
cmp [Word cs:si+MS.wantedperiod],0
jz mt_Return
xor ax,ax
mov al,[cs:si+MS.toneportspeed]
cmp [Byte cs:si+MS.toneportdirec],0
jnz mt_TonePortaUp
mt_TonePortaDown:
add [cs:si+MS.period],ax
mov ax,[cs:si+MS.wantedperiod]
cmp ax,[cs:si+MS.period]
jg mt_TonePortaSetPer
mov [cs:si+MS.period],ax
mov [Word cs:si+MS.wantedperiod],0
jmp mt_TonePortaSetPer
mt_TonePortaUp:
sub [cs:si+MS.period],ax
mov ax,[cs:si+MS.wantedperiod]
cmp ax,[cs:si+MS.period]
jl mt_TonePortaSetPer
mov [cs:si+MS.period],ax
mov [Word cs:si+MS.wantedperiod],0
mt_TonePortaSetPer:
mov cx,[cs:si+MS.period]
mov al,[cs:si+MS.glissfunk]
and al,0Fh
jz mt_GlissSkip
mov al,[cs:si+MS.finetune]
mov bl,61*2
mul bl
push di
mov di,offset mt_PeriodTable
add di,ax
mov bx,0
mt_GlissLoop:
cmp cx,[cs:bx+di]
jnb mt_GlissFound
add bx,2
cmp bx,61*2
jb mt_GlissLoop
mov bx,59*2
mt_GlissFound:
mov cx,[cs:bx+di]
pop di
mt_GlissSkip:
call mt_PerNop2
ret
endp mt_TonePortamento
; Effect 4 -- Vibrato
proc mt_Vibrato near
mov al,[cs:si+MS.cmdlo]
or al,al
jz mt_Vibrato2
mov cl,[cs:si+MS.vibratocmd]
and al,0fh
jz mt_vibskip
and cl,0F0h
or cl,al
mt_vibskip:
mov al,[cs:si+MS.cmdlo]
and al,0F0h
jz mt_vibskip2
and cl,0Fh
or cl,al
mt_vibskip2:
mov [cs:si+MS.vibratocmd],cl
mt_Vibrato2:
mov al,[cs:si+MS.vibratopos]
mov bx,offset mt_VibratoTable
shr ax,2
and ax,001Fh
xor cx,cx
mov cl,[cs:si+MS.wavecontrol]
and cl,03h
jz mt_vib_sine
shl al,3
cmp cl,1
jz mt_vib_rampdown
mov cl,255
jmp mt_vib_set
mt_vib_rampdown:
cmp [Byte cs:si+MS.vibratopos],0
jnl mt_vib_rampdown2
mov cl,255
sub cl,al
jmp mt_vib_set
mt_vib_rampdown2:
mov cl,al
jmp mt_vib_set
mt_vib_sine:
add bl,al
mov cl,[cs:bx]
mt_vib_set:
mov al,[cs:si+MS.vibratocmd]
and al,15
mul cl
shr ax,7
mov cx,ax
mov ax,[cs:si+MS.period]
cmp [Byte cs:si+MS.vibratopos],0
jl mt_VibratoNeg ; BMI
add ax,cx
jmp mt_Vibrato3
mt_VibratoNeg:
sub ax,cx
mt_Vibrato3:
mov cx,ax
call mt_PerNop2
mov al,[cs:si+MS.vibratocmd]
shr ax,2
and ax,3Ch
add [cs:si+MS.vibratopos],al
ret
endp mt_Vibrato
; Effect 5 -- Tone and Volume Slide
proc mt_TonePlusVolSlide near
call mt_TonePortNoChange
jmp mt_VolumeSlide
endp mt_TonePlusVolSlide
; Effect 6 -- Vibrato and Volume Slide
proc mt_VibratoPlusVolSlide near
call mt_Vibrato2
jmp mt_VolumeSlide
endp mt_VibratoPlusVolSlide
; Effect 7 -- Tremolo
proc mt_Tremolo near
mov al,[Byte cs:si+MS.cmdlo]
or al,al
jz mt_Tremolo2
mov cl,[cs:si+MS.tremolocmd]
and al,0Fh
jz mt_treskip
and cl,0F0h
or cl,al
mt_treskip:
mov al,[Byte cs:si+MS.cmdlo]
and al,0F0h
jz mt_treskip2
and cl,0Fh
or cl,al
mt_treskip2:
mov [cs:si+MS.tremolocmd],cl
mt_Tremolo2:
mov al,[cs:si+MS.tremolopos]
shr al,2
and ax,001Fh
xor cx,cx
mov cl,[cs:si+MS.wavecontrol]
shr cl,4
and cl,03h
jz mt_tre_sine
shl al,3
cmp cl,1
jz mt_tre_rampdown
mov cl,255
jmp mt_tre_set
mt_tre_rampdown:
cmp [Byte cs:si+MS.vibratopos],0
jnb mt_tre_rampdown2
mov cl,255
sub cl,al
jmp mt_tre_set
mt_tre_rampdown2:
mov cl,al
jmp mt_tre_set
mt_tre_sine:
xor bx,bx
mov bl,al
mov cl,[cs:bx+offset mt_VibratoTable]
mt_tre_set:
mov al,[cs:si+MS.tremolocmd]
and al,0Fh
mul cl
mov cx,ax
shr cx,6
mov al,[cs:si+MS.volume]
cmp [Byte cs:si+MS.tremolopos],0
jb mt_TremoloNeg ; BMI jns
add al,cl
jmp mt_Tremolo3
mt_TremoloNeg:
sub al,cl
mt_Tremolo3:
jnb mt_TremoloSkip
xor ax,ax
mt_TremoloSkip:
cmp al,40h
jb mt_TremoloOK ; BLS
mov al,40h
mt_TremoloOK:
call volequ
mov al,[cs:si+MS.tremolocmd]
shr al,2
and al,3Ch
add [cs:si+MS.tremolopos],al
ret
endp mt_Tremolo
; Effect 9 -- Sample Offset
proc mt_SampleOffset near
mov al,[Byte cs:si+MS.cmdlo]
or al,al
jz mt_sononew
mov [cs:si+MS.sampleoffset],al
mt_sononew:
mov al,[cs:si+MS.sampleoffset] ; Variance in Protracker code.
shl ax,8
; cmp ax,[cs:si+MS.reallength]
; jge mt_sofskip
mov cx,ax
or cx,cx
jnz mt_dontset
dec cx
mt_dontset:
mov ax,[Word cs:si+MS.start]
mov dx,[Word cs:si+(offset (MS).start)+2]
add ax,cx
adc dx,0
mov [Word cs:si+MS.start],ax
mov [Word cs:si+(offset (MS).start)+2],dx
ret
mt_sofskip:
ret
endp mt_SampleOffset
; Effect A -- Volume Slide
proc mt_VolumeSlide near
mov al,[cs:si+MS.cmdlo]
shr al,4
or al,al
jz mt_VolSlideDown
mt_VolSlideUp:
add [Byte cs:si+MS.volume],al
cmp [Byte cs:si+MS.volume],40h
jb mt_vsuskip
mov [Byte cs:si+MS.volume],40h
mt_vsuskip:
mov al,[Byte cs:si+MS.volume]
call volequ
ret
mt_VolSlideDown:
mov al,[cs:si+MS.cmdlo]
and al,0Fh
mt_VolSlideDown2:
sub [Byte cs:si+MS.volume],al
jnb mt_vsdskip
mov [Byte cs:si+MS.volume],0
mt_vsdskip:
mov al,[Byte cs:si+MS.volume]
call volequ
ret
endp mt_VolumeSlide
; Effect B -- Position Jump
proc mt_PositionJump near
mov al,[Byte cs:si+MS.cmdlo] ; Get where to jump
dec al ; Update the
mov [cs:mt_SongPos],al ; information.
mt_pj2: mov [Byte cs:mt_PBreakPos],0
mov [Byte cs:mt_PosJumpFlag],1
ret
endp mt_PositionJump
; Effect C -- Volume Change
proc mt_VolumeChange near
mov al,[Byte cs:si+MS.cmdlo] ; Get value for volume
cmp al,40h ; Is it greater than 40h?
jb mt_VolumeOK ; Nope
mov al,40h
mt_VolumeOK:
mov [cs:si+MS.volume],al ; Get it again
call volequ
ret
endp mt_VolumeChange
; Effect D -- Pattern Break
proc mt_PatternBreak near
mov al,[Byte cs:si+MS.cmdlo] ; Break to where?
mov cl,al
shr al,4
mov bl,10
mul bl
and cl,0Fh
add al,cl
cmp al,63
jg mt_pj2
mov [cs:mt_PBreakPos],al
mov [Byte cs:mt_PosJumpFlag],1
ret
endp mt_PatternBreak
; Effect F -- Set Speed
; Doesn't handle Protracker extended speeds.
proc mt_SetSpeed near
mov al,[Byte cs:si+MS.cmdlo] ; Get value for speed
or al,al
jz mt_SpeedLeave
cmp al,32
jnb mt_SpeedExt
mt_SpeedSet:
mov [Byte cs:mt_counter],0
mov [Byte cs:mt_speed],al
mt_SpeedLeave:
ret
mt_SpeedExt:
ret
endp mt_SetSpeed
proc mt_CheckMoreEfx near
mov bl,[cs:si+MS.cmd]
and bl,0Fh
cmp bl,09h
jz mt_SampleOffset
cmp bl,0Bh
jz mt_PositionJump
cmp bl,0Dh
jz mt_PatternBreak
cmp bl,0Eh
jz mt_E_Commands
cmp bl,0Fh
jz mt_SetSpeed
cmp bl,0Ch
jz mt_VolumeChange
jmp mt_PerNop
endp mt_CheckMoreEfx
proc mt_E_Commands near
mov bl,[Byte cs:si+MS.cmdlo]
and bl,0F0h
shr bl,4
cmp bl,0
jz mt_FilterOnOff
cmp bl,1
jz mt_FinePortaUp
cmp bl,2
jz mt_FinePortaDown
cmp bl,3
jz mt_SetGlissControl
cmp bl,4
jz mt_SetVibratoControl
cmp bl,5
jz mt_SetFineTune
cmp bl,6
jz mt_JumpLoop
cmp bl,7
jz mt_SetTremoloControl
cmp bl,0Eh
jz mt_PatternDelay
cmp bl,9
jz mt_RetrigNote
cmp bl,0Ah
jz mt_VolumeFineUp
cmp bl,0Bh
jz mt_VolumeFineDown
cmp bl,0Ch
jz mt_NoteCut
cmp bl,0Dh
jz mt_NoteDelay
ret
endp mt_E_Commands
;──────────────────────────────────────────────────────────────────────────
; Effect E
;──────────────────────────────────────────────────────────────────────────
; Effect 0 -- FilterOnOff
proc mt_FilterOnOff near
mov al,[Byte cs:si+MS.cmdlo]
and al,1
sal al,1
; Amiga
; Stuff
ret
endp mt_FilterOnOff
; Effect 1 -- Fine Porta Up
proc mt_FinePortaUp near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov [Byte cs:mt_LowMask],0Fh
jmp mt_PortaUp
endp mt_FinePortaUp
; Effect 2 -- Fine Porta Down
proc mt_FinePortaDown near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov [Byte cs:mt_LowMask],0Fh
jmp mt_PortaDown
endp mt_FinePortaDown
; Effect 3 -- Set Gliss Control
proc mt_SetGlissControl near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
and [Byte cs:si+MS.glissfunk],0F0h
or [cs:si+MS.glissfunk],al
ret
endp mt_SetGlissControl
; Effect 4 -- Set Vibrato Control
proc mt_SetVibratoControl near
mov al,[cs:si+MS.cmdlo]
and al,0Fh
and [Byte cs:si+MS.wavecontrol],0F0h
or [cs:si+MS.wavecontrol],al
ret
endp mt_SetVibratoControl
; Effect 5 -- Set Fine Tune
proc mt_SetFineTune near
mov al,[cs:si+MS.cmdlo]
and al,0Fh
mov [cs:si+MS.finetune],al
ret
endp mt_SetFineTune
; Effect 6 -- Jump Loop
proc mt_JumpLoop near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jz mt_SetLoop
cmp [Byte cs:si+MS.loopcount],0
jz mt_jumpcnt
dec [Byte cs:si+MS.loopcount]
jz mt_Return
mt_jmploop:
mov al,[cs:si+MS.pattpos]
mov [cs:mt_PBreakPos],al
mov [Byte cs:mt_PBreakFlag],1
ret
mt_jumpcnt:
mov [cs:si+MS.loopcount],al
jmp mt_jmploop
mt_SetLoop:
; xor dx,dx
mov ax,[cs:mt_PatternPos]
mov bx,48
; call DivIt
div bl
and ax,63
mov [cs:si+MS.pattpos],al
ret
endp mt_JumpLoop
; Effect 7 -- Set Tremolo Control
proc mt_SetTremoloControl near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
shl al,4
and [Byte cs:si+MS.wavecontrol],0Fh
or [cs:si+MS.wavecontrol],al
ret
endp mt_SetTremoloControl
; Effect 9 -- Retrig Note
proc mt_RetrigNote near
mov bl,[Byte cs:si+MS.cmdlo]
and bl,0Fh
jz mt_rtnend
xor ax,ax
mov al,[cs:mt_counter]
or al,al
jnz mt_rtnskp
mov al,[cs:si+MS.note]
or al,al
jnz mt_rtnend
; mov [Byte cs:mt_counter],0
xor ax,ax
mov al,[cs:mt_counter]
mt_rtnskp:
div bl
xchg ah,al
or al,al
jnz mt_rtnend
mt_DoRetrig:
mov [Byte cs:EfxFlag],1
call mt_DoIns
mov [Byte cs:EfxFlag],0
mt_rtnend:
ret
endp mt_RetrigNote
; Effect A -- Volume Fine Up
proc mt_VolumeFineUp near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jmp mt_VolSlideUp
endp mt_VolumeFineUp
; Effect B -- Volume Fine Down
proc mt_VolumeFineDown near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[cs:si+MS.cmdlo]
and al,0Fh
jmp mt_VolSlideDown2
endp mt_VolumeFineDown
; Effect C -- Note Cut
proc mt_NoteCut near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp al,[cs:mt_counter]
jnz mt_Return
mov [Byte cs:si+MS.volume],0
mov al,[Byte cs:si+MS.volume]
call volequ
ret
endp mt_NoteCut
; Effect D -- Note Delay
proc mt_NoteDelay near
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp al,[cs:mt_counter]
jnz mt_Return
mov al,[cs:si]
and al,00111111b
jz mt_Return
jmp mt_DoRetrig
endp mt_NoteDelay
; Effect E -- Pattern Delay
proc mt_PatternDelay near
cmp [Byte cs:mt_counter],0
jnz mt_Return
mov al,[Byte cs:si+MS.cmdlo]
and al,0Fh
cmp [Byte cs:mt_PattDelayTime2],0
jnz mt_Return
inc al
mov [cs:mt_PattDelayTime],al
ret
endp mt_PatternDelay
proc doramp near
push bx si
mov ah,0
cmp [Byte cs:si+MS.MasterVolume],0
jz @@ZeroVol
mul [Byte cs:si+MS.MasterVolume]
inc ah
@@ZeroVol:
mov bl,ah
xor bh,bh
shl bx,1
mov ax,[cs:bx+mt_VolTable]
jmp slideramp2
slideramp:
push bx si
slideramp2:
mov si,ax
mov dx,[cs:u_Command]
mov al,0Dh
out dx,al
add dl,2
mov al,3
out dx,al
sub dl,2
mov al,89h
out dx,al
inc dx
in ax,dx
push si
push ax
shr ax,8
shr si,8
cmp ax,si
jz @@Done2
jb @@OK
xchg si,ax
@@OK:
push ax
mov dx,[cs:u_Command]
mov al,7
out dx,al
add dx,2
pop ax
out dx,al
mov dx,[cs:u_Command]
mov al,8
out dx,al
add dx,2
mov ax,si
out dx,al
mov dx,[cs:u_Command]
mov al,6
out dx,al
add dx,2
mov al,00111111b
out dx,al
mov bl,00000000b
pop ax
pop si
cmp ax,si
jb @@OK2
or bl,01000000b
@@OK2:
mov dx,[cs:u_Command]
mov al,0Dh
out dx,al
add dx,2
mov al,bl
out dx,al
jmp @@Done
@@Done2:
pop ax ax
@@Done:
pop si bx
ret
endp doramp
proc volequ near
push bx si
mov [cs:si+MS.DecVolume],al
mov ah,0
cmp [Byte cs:si+MS.MasterVolume],0
jz @@ZeroVol
mul [Byte cs:si+MS.MasterVolume]
inc ah
@@ZeroVol:
mov bl,ah
xor bh,bh
shl bx,1
mov ax,[cs:bx+mt_VolTable]
@@Skip: mov [cs:si+MS.sc_Vol],ax
pop si bx
ret
endp volequ
proc DivIt near
or bx,bx
stc
jz Div1
mov cx,ax
mov ax,dx
xor dx,dx
div bx
xchg cx,ax
div bx
xchg dx,cx
clc
Div1: ret
endp DivIt
proc mt_PerNop near
mov cx,[cs:si+MS.period] ; get period Value
proc mt_PerNop2 near
mov ax,cx
and ax,0FFFh
or ax,ax
jz @@OutIt
push dx bx ax
mov bx,19
mov dx,36h
mov ax,9E9Ah
call DivIt
pop bx
call DivIt
pop bx dx
@@OutIt: mov [cs:si+MS.sc_Note],ax
ret
endp mt_PerNop2
endp mt_PerNop
SizeSoundSeg = $-StartSoundSeg
ends GUSSound